﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using PedesTrainProject.Data;

namespace PedesTrainProject.Core
{
    public class SimulationCreator : ICoreGUI
    {
        private GUI.SimulationCreator simulationCreator;
        private Grid.Grid tempGrid = new Grid.Grid(4, 4);
        private FileHandler fileHandler;
        private DateTime startTime = new DateTime(2012, 1, 1, 6, 0, 0);
        private DateTime endTime = new DateTime(2012, 1, 2, 6, 0, 0);

        public void setStartTime(DateTime _startTime)
        {
            startTime = _startTime;
        }
        public void setEndTime(DateTime _endTime)
        {
            endTime = _endTime;
        }
        public DateTime getStartTime()
        {
            return startTime;
        }
        public DateTime getEndTime()
        {
            return endTime;
        }
        public Grid.Grid TempGrid
        {
            get { return tempGrid; }
            set { tempGrid = value; }
        }

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Core.SimulationCreator sim = new Core.SimulationCreator();
        }

        public SimulationCreator()
        {
            simulationCreator = new GUI.SimulationCreator(this);
            Application.Run(simulationCreator);   
        }
        private void adjustGrid(Grid.Grid grid)
        {

        }
        private void adjustCars(Traffic.CarFlow carFlow)
        {

        }
        public Grid.Tile createTile(Grid.Road _road)
        {
            return new Grid.Tile(_road);
        }

        public Grid.Road createRoad(string _name, string _skin, Grid.Directions direction)
        {
            return new Grid.Road(_name, _skin, direction);
        }

        public void addTile(Grid.Tile _tile, System.Windows.Vector position)
        {
            tempGrid.addTile(_tile, position);
        }
        public void adjustPedestrians(KeyValuePair<int, int> amounts)
        {

        }
        public bool crossingPresent(System.Windows.Vector position)
        {
            System.Console.WriteLine(Core.Calculations.tileListPosition(Core.Calculations.calculateTileCoordinates(position)));
            try
            {
                if (tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.Name != "crossing" && tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.Name != "Tcrossing" && tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.Skin == "none")
                    return false;
                else
                    return true;
            }
            catch (NullReferenceException)
            {
                return false;
            }
        }

        public bool pedestrianCrossingPresent(System.Windows.Vector position)
        {
            if (tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))] != null)
            {
                if (tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.Skin!="none")
                    return true;
                else
                    return false;
            }
            else
                return false;
        }

        public string getRoadName(System.Windows.Vector position)
        {
            return tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.Name;
        }

        public string getRoadSkin(System.Windows.Vector position)
        {
            return tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.Skin;
        }

        private void adjustInFlowFlags(List<Grid.InFlowFlag> inFlowFlags)
        {

        }
        public Grid.CarLight adjustCarLight(List<int> _intervals, Grid.Directions direction)
        {
            return new Grid.CarLight(_intervals, direction);
        }

        private void adjustCarLights(List<Grid.CarLight> CarLights)
        {

        }
        private void adjustSpeed(int speed)
        {

        }

        private void adjustTime(DateTime start_time, DateTime end_time)
        {

        }

        public void addCarLight(List<int> intervals,System.Windows.Vector position)
        {
            Grid.Road crossing = tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road;
            //crossing.addCarLight(intervals);
        }

        public List<int> getIntervals(System.Windows.Vector position)
        {
            List<int> intervals = new List<int>();
            if (tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.Name == "crossing")
            {
                
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);


                for (int i = 0; i < 4; i++)
                {
                    intervals[2 * i] = tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[i].Intervals[0];
                    intervals[2 * i + 1] = tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[i].Intervals[1];
                }
                intervals.Add(tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[0].Intervals[2]);
            }
            if (tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.Name == "crossing")
            {
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);

                for (int i = 0; i < 4; i++)
                {
                    intervals[2 * i] = tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[i].Intervals[0];
                    intervals[2 * i + 1] = tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[i].Intervals[1];
                }
                intervals.Add(tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[0].Intervals[2]);
            }
            if (tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.Name == "Tcrossing")
            {

                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
       
                for (int i = 0; i < 3; i++)
                {
                    intervals[2 * i] = tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[i].Intervals[0];
                    intervals[2 * i + 1] = tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[i].Intervals[1];
                }
                intervals.Add(tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[0].Intervals[2]);
            }
            return intervals;
        }



        public void setIntervals(List<int> intervals, System.Windows.Vector position)
        {
            Grid.Road crossing = tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road;
            Grid.Directions direction = Grid.Directions.None;

            for (int i = 0; i < 4; i++)
            {
                List<int> inter = new List<int>();
                inter.Add(intervals[2 * i]);
                    inter.Add(intervals[2*i+1]);
                    inter.Add(intervals[8]);
                    if (i == 0) direction = Grid.Directions.North;
                    if (i == 1) direction = Grid.Directions.East;
                    if (i == 2) direction = Grid.Directions.South;
                    if (i == 3) direction = Grid.Directions.West;

                    tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[i] = new Grid.CarLight(inter, direction);
            }

        }

        public void setInitialLights(bool horizontal, System.Windows.Vector position)
        {
            Grid.Road crossing = tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road;

            if (horizontal == false)
            {
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[0].Green = true;
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[2].Green = true;
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[0].Red = false;
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[2].Red = false;
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[1].Red = true;
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[3].Red = true;
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[1].Green = false;
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[3].Green = false;
            }
            else
            {
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[1].Green = true;
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[3].Green = true;
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[1].Red = false;
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[3].Red = false;
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[0].Red = true;
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[2].Red = true;
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[0].Green = false;
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.CarLights[2].Green = false;
            }

        }

        public List<int> getPedestrianIntervals(System.Windows.Vector position)
        {
            Grid.Road crossing = tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road;
            List<int> intervals = new List<int>();
            if (crossing.Skin == "hor" || crossing.Skin == "ver")
            {
                try
                {
                    intervals.Add(1);
                    intervals.Add(1);
                    intervals[0] = crossing.PedestrianLights[0].Intervals[0];
                    intervals[1] = crossing.PedestrianLights[0].Intervals[1];
                }
                catch (ArgumentOutOfRangeException) { }
            }
            if (crossing.Skin == "both")
            {
                try
                {
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
              
                intervals[0] = crossing.PedestrianLights[0].Intervals[0];
                intervals[1] = crossing.PedestrianLights[0].Intervals[1];
                intervals[2] = crossing.PedestrianLights[1].Intervals[0];
                intervals[3] = crossing.PedestrianLights[1].Intervals[1];
                intervals[4] = crossing.PedestrianLights[0].Intervals[2];
                intervals[5] = crossing.PedestrianLights[1].Intervals[2];
                }
                catch (ArgumentOutOfRangeException) { }
            }
            
            return intervals;
        }

        public void setPedestrianIntervals(List<int> intervals, System.Windows.Vector position)
        {
            Grid.Road crossing = tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road;
            if (crossing.Skin == "hor" || crossing.Skin == "ver")
            {
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.PedestrianLights[0].Intervals[0] = intervals[0];
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.PedestrianLights[0].Intervals[1] = intervals[1];
            }
            if (crossing.Skin == "both")
            {
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
                intervals.Add(1);
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.PedestrianLights[0].Intervals[0] = intervals[0];
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.PedestrianLights[0].Intervals[1] = intervals[1];
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.PedestrianLights[1].Intervals[0] = intervals[2];
                tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(position))].Road.PedestrianLights[1].Intervals[1] = intervals[3];
            }
        }

        public ICoreGUIRun startSimulation(Graphics e, PictureBox _pb, Bitmap drawArea, GUI.SimulationCreator _scGUI)
        {
            Simulation simulation = new Simulation(this,e,_pb,drawArea,_scGUI,startTime,endTime);
            return simulation;
        }

        public void addInFlowFlag(List<KeyValuePair<DateTime, int>> _intervals, System.Windows.Vector _position)
        {
            for (int i = 0; i < tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(_position))].Road.Lanes.Count; i++)
            {
                bool add = true;
                if (Calculations.tileListPosition(Calculations.calculateTileCoordinates(_position)) - tempGrid.Width < 0 && tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(_position))].Road.Lanes[i].Direction == Grid.Directions.North) add = false;
                if ((Calculations.tileListPosition(Calculations.calculateTileCoordinates(_position)) + 1) % tempGrid.Width == 0 && tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(_position))].Road.Lanes[i].Direction == Grid.Directions.East) add = false;
                if (Calculations.tileListPosition(Calculations.calculateTileCoordinates(_position)) + tempGrid.Width >= tempGrid.Tiles.Count && tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(_position))].Road.Lanes[i].Direction == Grid.Directions.South) add = false;
                if (Calculations.tileListPosition(Calculations.calculateTileCoordinates(_position)) % tempGrid.Width == 0 && tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(_position))].Road.Lanes[i].Direction == Grid.Directions.West) add = false;

                if (add)
                {
                    tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(_position))].Road.Lanes[i].InFlow = new Grid.InFlowFlag(_intervals);
                    break;
                }
            }
        }

        public void setInFlowFlag(List<KeyValuePair<DateTime, int>> _intervals, System.Windows.Vector _position)
        {
            foreach (Grid.Lane lane in tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(_position))].Road.Lanes)
            {
                if (lane.InFlow != null) lane.InFlow.Intervals = _intervals;
            }
            
        }

        public List<KeyValuePair<DateTime,int>> getInFlowFlag(System.Windows.Vector _position)
        {
       //     Grid.Directions _direction, _direction1;
            Grid.Road crossing = tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(_position))].Road;

            foreach (Grid.Lane lane in crossing.Lanes)
            {
                if (lane.InFlow != null)
                    return lane.InFlow.Intervals;
            }
            return null;

        }

        public bool canSetInFlowFlag(System.Windows.Vector _position)
        {
            Grid.Road crossing = tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(_position))].Road;

            if (crossing.Lanes.Count == 0) return false;

            foreach (Grid.Lane lane in tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(_position))].Road.Lanes)
            {
                if (lane.InFlow != null)
                    return false;
            }

            if (Calculations.calculateTileCoordinates(_position).Y == 0 || Calculations.calculateTileCoordinates(_position).Y == 3 && crossing.Lanes[0].Direction == Grid.Directions.North || crossing.Lanes[0].Direction == Grid.Directions.South)
            {
                return true;
            }
            if (Calculations.calculateTileCoordinates(_position).X == 0 || Calculations.calculateTileCoordinates(_position).X == 3 && crossing.Lanes[0].Direction == Grid.Directions.West || crossing.Lanes[0].Direction == Grid.Directions.East)
            {
                return true;
            }
            else
            return false;
        }

        public bool inFlowFlagPresent(System.Windows.Vector _position)
        {
            foreach (Grid.Lane lane in tempGrid.Tiles[Calculations.tileListPosition(Calculations.calculateTileCoordinates(_position))].Road.Lanes)
            {
                if (lane.InFlow != null)
                    return true;
            }
            return false;
        }

        public void SaveGridLayout()
        {
    
        }

        public bool SaveGridLayout(string filePath)
        {
            bool saved = false;
            try
            {
                if (fileHandler == null)
                    fileHandler = new FileHandler();

                fileHandler.saveGrid(this.tempGrid, filePath);
                saved = true;
            }
            catch
            {
            }
            return saved;
        }


        public bool LoadGridLayout(string filePath)
        {
            bool loaded = false;

            try
            {
                if (fileHandler == null)
                    fileHandler = new FileHandler();

                this.tempGrid = fileHandler.loadGrid(filePath);
                loaded = true;
            }
            catch
            {
            }

            return loaded;
        }

        public Grid.Grid LoadGridLayout()
        {
            return tempGrid;
        }
        public List<Grid.Tile> GetTiles()
        {
            return tempGrid.Tiles;
        }

        public Statistics getStatistic()
        {
            throw new NotImplementedException();
        }
    }
}
